From d3bc4224c6c246f064c0b9dd5a78d0ef21e2e8b3 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Sat, 5 Jul 2003 13:48:17 +0000 Subject: [PATCH] bitkeeper revision 1.259.2.1 (3f06d721WrVqlnf2Z2shaoLBGWSRng) Many files: Removed 'hypercall-privilege-changing' functionality -- rings 2 & 3 will just have to bounce via ring 1. IOPL functionality has become a dom0_op, as it seems cleanest to have all privileged operations under one top-level syscall. --- xen/arch/i386/entry.S | 1 - xen/arch/i386/process.c | 15 ++---- xen/arch/i386/traps.c | 17 ------- xen/common/dom0_ops.c | 9 +++- xen/include/asm-i386/processor.h | 1 - xen/include/hypervisor-ifs/dom0_ops.h | 48 +++++++++++-------- xen/include/hypervisor-ifs/hypervisor-if.h | 1 - .../arch/xeno/drivers/dom0/dom0_core.c | 6 --- .../arch/xeno/drivers/dom0/dom0_ops.h | 9 ++-- .../arch/xeno/kernel/ioport.c | 27 ++++++----- .../arch/xeno/kernel/process.c | 15 +++--- .../arch/xeno/kernel/setup.c | 15 ++++-- .../include/asm-xeno/hypervisor.h | 12 ----- .../include/asm-xeno/processor.h | 2 +- 14 files changed, 77 insertions(+), 101 deletions(-) diff --git a/xen/arch/i386/entry.S b/xen/arch/i386/entry.S index 33d533a283..b60b502288 100644 --- a/xen/arch/i386/entry.S +++ b/xen/arch/i386/entry.S @@ -647,7 +647,6 @@ ENTRY(hypervisor_call_table) .long SYMBOL_NAME(do_dom_mem_op) .long SYMBOL_NAME(do_multicall) .long SYMBOL_NAME(do_kbd_op) - .long SYMBOL_NAME(do_set_priv_levels) .rept NR_syscalls-((.-hypervisor_call_table)/4) .long SYMBOL_NAME(sys_ni_syscall) .endr diff --git a/xen/arch/i386/process.c b/xen/arch/i386/process.c index 695b581507..5b604ca413 100644 --- a/xen/arch/i386/process.c +++ b/xen/arch/i386/process.c @@ -348,19 +348,10 @@ void __switch_to(struct task_struct *prev_p, struct task_struct *next_p) } -long do_set_priv_levels(unsigned int new_io_pl, unsigned int new_hypercall_pl) +/* XXX Currently the 'domain' field is ignored! XXX */ +long do_iopl(unsigned int domain, unsigned int new_io_pl) { struct pt_regs *regs = GET_SYSCALL_REGS(current); - - /* - * Any domain can reduce privilege required for hypercall access. - * Note that access from ring 1 cannot be relinquished. - */ - current->thread.hypercall_pl = new_hypercall_pl & 3; - - /* Only privileged domains can acquire access to I/O ports. */ - if ( IS_PRIV(current) ) - regs->eflags = (regs->eflags & 0xffffcfff) | ((new_io_pl&3) << 12); - + regs->eflags = (regs->eflags & 0xffffcfff) | ((new_io_pl&3) << 12); return 0; } diff --git a/xen/arch/i386/traps.c b/xen/arch/i386/traps.c index e4af21065b..8ca6b90ccf 100644 --- a/xen/arch/i386/traps.c +++ b/xen/arch/i386/traps.c @@ -401,23 +401,6 @@ asmlinkage void do_general_protection(struct pt_regs *regs, long error_code) */ if ( (error_code & 3) == 2 ) { - /* - * Hypercalls from rings 2 or 3 fall through to here. If permitted, we - * will transfer control to the requested hypercall. - */ - if ( ((error_code>>3) == HYPERVISOR_CALL_VECTOR) && - (current->thread.hypercall_pl >= (regs->xcs & 3)) ) - { - __asm__ __volatile__ ( - "movl %0,%%esp \n" - "sti \n" - "andl $255,%%eax \n" - "call *hypervisor_call_table(,%%eax,4) \n" - "movl %%eax,0x18(%%esp) \n" - "jmp ret_from_intr \n" - : : "r" (regs) ); - } - /* This fault must be due to instruction. */ ti = current->thread.traps + (error_code>>3); if ( ti->dpl >= (regs->xcs & 3) ) diff --git a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c index e65eeb0df1..281fb509b9 100644 --- a/xen/common/dom0_ops.c +++ b/xen/common/dom0_ops.c @@ -67,7 +67,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op) long ret = 0; dom0_op_t op; - if ( current->domain != 0 ) + if ( !IS_PRIV(current) ) return -EPERM; if ( copy_from_user(&op, u_dom0_op, sizeof(op)) ) @@ -239,6 +239,13 @@ long do_dom0_op(dom0_op_t *u_dom0_op) break; } + case DOM0_IOPL: + { + extern long do_iopl(unsigned int, unsigned int); + ret = do_iopl(op.u.iopl.domain, op.u.iopl.iopl); + } + break; + default: ret = -ENOSYS; diff --git a/xen/include/asm-i386/processor.h b/xen/include/asm-i386/processor.h index 80ec83e745..eb0ca7001a 100644 --- a/xen/include/asm-i386/processor.h +++ b/xen/include/asm-i386/processor.h @@ -356,7 +356,6 @@ struct thread_struct { int fast_trap_idx; struct desc_struct fast_trap_desc; trap_info_t traps[256]; - int hypercall_pl; }; #define IDT_ENTRIES 256 diff --git a/xen/include/hypervisor-ifs/dom0_ops.h b/xen/include/hypervisor-ifs/dom0_ops.h index d8da108d66..b437acec26 100644 --- a/xen/include/hypervisor-ifs/dom0_ops.h +++ b/xen/include/hypervisor-ifs/dom0_ops.h @@ -19,9 +19,10 @@ #define DOM0_STOPDOMAIN 11 #define DOM0_GETDOMAININFO 12 #define DOM0_BUILDDOMAIN 13 +#define DOM0_IOPL 14 -#define MAX_CMD_LEN 256 -#define MAX_DOMAIN_NAME 16 +#define MAX_CMD_LEN 256 +#define MAX_DOMAIN_NAME 16 typedef struct dom0_newdomain_st { @@ -60,32 +61,38 @@ typedef struct domain_launch typedef struct dom0_bvtctl_st { - unsigned long ctx_allow; /* context switch allowance */ + unsigned long ctx_allow; /* context switch allowance */ } dom0_bvtctl_t; typedef struct dom0_adjustdom_st { unsigned int domain; /* domain id */ - unsigned long mcu_adv; /* mcu advance: inverse of weight */ - unsigned long warp; /* time warp */ - unsigned long warpl; /* warp limit */ - unsigned long warpu; /* unwarp time requirement */ + unsigned long mcu_adv; /* mcu advance: inverse of weight */ + unsigned long warp; /* time warp */ + unsigned long warpl; /* warp limit */ + unsigned long warpu; /* unwarp time requirement */ } dom0_adjustdom_t; typedef struct dom0_getdominfo_st { - unsigned int domain; /* All returns except domain */ - char name[MAX_DOMAIN_NAME]; - int processor; - int has_cpu; - int state; - int hyp_events; - unsigned long mcu_advance; - unsigned long pg_head; - unsigned int tot_pages; - long long cpu_time; + unsigned int domain; /* All returns except domain */ + char name[MAX_DOMAIN_NAME]; + int processor; + int has_cpu; + int state; + int hyp_events; + unsigned long mcu_advance; + unsigned long pg_head; + unsigned int tot_pages; + long long cpu_time; } dom0_getdominfo_t; +typedef struct dom0_iopl_st +{ + unsigned int domain; + unsigned int iopl; +} dom0_iopl_t; + #ifndef NO_DOM0_OP_T typedef struct dom0_op_st { @@ -95,11 +102,12 @@ typedef struct dom0_op_st dom0_newdomain_t newdomain; dom0_killdomain_t killdomain; dom0_getmemlist_t getmemlist; - dom0_bvtctl_t bvtctl; - dom0_adjustdom_t adjustdom; + dom0_bvtctl_t bvtctl; + dom0_adjustdom_t adjustdom; dom_meminfo_t meminfo; dom0_getdominfo_t getdominfo; - } + dom0_iopl_t iopl; + } u; } dom0_op_t; #endif diff --git a/xen/include/hypervisor-ifs/hypervisor-if.h b/xen/include/hypervisor-ifs/hypervisor-if.h index 2516f84554..0dfd07cb60 100644 --- a/xen/include/hypervisor-ifs/hypervisor-if.h +++ b/xen/include/hypervisor-ifs/hypervisor-if.h @@ -48,7 +48,6 @@ #define __HYPERVISOR_dom_mem_op 17 #define __HYPERVISOR_multicall 18 #define __HYPERVISOR_kbd_op 19 -#define __HYPERVISOR_set_priv_levels 20 /* And the trap vector is... */ #define TRAP_INSTR "int $0x82" diff --git a/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_core.c b/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_core.c index b42abc45e4..1aa5ef0d54 100644 --- a/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_core.c +++ b/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_core.c @@ -334,12 +334,6 @@ static int cmd_write_proc(struct file *file, const char *buffer, copy_from_user(&op, buffer, sizeof(dom0_op_t)); - /* do some sanity checks */ - if(op.cmd > MAX_CMD){ - ret = -ENOSYS; - goto out; - } - if ( op.cmd == MAP_DOM_MEM ) { ret = dom_map_mem(op.u.dommem.domain, op.u.dommem.start_pfn, diff --git a/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_ops.h b/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_ops.h index 8562591e1e..23006eae0d 100644 --- a/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_ops.h +++ b/xenolinux-2.4.21-sparse/arch/xeno/drivers/dom0/dom0_ops.h @@ -18,9 +18,8 @@ #endif /* Extra commands dealt with by Xenolinux. */ -#define MAP_DOM_MEM 14 -#define DO_PGUPDATES 15 -#define MAX_CMD 16 +#define MAP_DOM_MEM 1014 +#define DO_PGUPDATES 1015 typedef struct dom_mem { @@ -50,8 +49,8 @@ typedef struct dom0_op_st dom_pgupdate_t pgupdate; dom_meminfo_t meminfo; dom0_getdominfo_t getdominfo; - } - u; + dom0_iopl_t iopl; + } u; } dom0_op_t; #endif /* __DOM0_DOM0_OPS_H__ */ diff --git a/xenolinux-2.4.21-sparse/arch/xeno/kernel/ioport.c b/xenolinux-2.4.21-sparse/arch/xeno/kernel/ioport.c index 7b30b8dcf2..c946fc4d37 100644 --- a/xenolinux-2.4.21-sparse/arch/xeno/kernel/ioport.c +++ b/xenolinux-2.4.21-sparse/arch/xeno/kernel/ioport.c @@ -3,6 +3,7 @@ #include #include #include +#include asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on) @@ -15,32 +16,32 @@ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on) asmlinkage int sys_iopl(unsigned long unused) { struct pt_regs *regs = (struct pt_regs *)&unused; - unsigned int new_io_pl = regs->ebx & 3; + unsigned int new_io_pl = regs->ebx; unsigned int old_io_pl = current->thread.io_pl; - unsigned int new_hypercall_pl = (regs->ebx >> 2) & 3; - unsigned int old_hypercall_pl = current->thread.hypercall_pl; + dom0_op_t op; - /* Need "raw I/O" privileges for direct port access. */ - if ( (new_io_pl > old_io_pl) && - (!capable(CAP_SYS_RAWIO) || !(start_info.flags & SIF_PRIVILEGED)) ) + if ( !(start_info.flags & SIF_PRIVILEGED) ) return -EPERM; - /* Just need generic root/admin privileges for direct hypercall access. */ - if ( (new_hypercall_pl > old_hypercall_pl) && !capable(CAP_SYS_ADMIN) ) + if ( new_io_pl > 3 ) + return -EINVAL; + + /* Need "raw I/O" privileges for direct port access. */ + if ( (new_io_pl > old_io_pl) && !capable(CAP_SYS_RAWIO) ) return -EPERM; /* Maintain OS privileges even if user attempts to relinquish them. */ - if ( new_hypercall_pl == 0 ) - new_hypercall_pl = 1; if ( (new_io_pl == 0) && (start_info.flags & SIF_PRIVILEGED) ) new_io_pl = 1; /* Change our version of the privilege levels. */ - current->thread.io_pl = new_io_pl; - current->thread.hypercall_pl = new_hypercall_pl; + current->thread.io_pl = new_io_pl; /* Force the change at ring 0. */ - HYPERVISOR_set_priv_levels(new_io_pl, new_hypercall_pl); + op.cmd = DOM0_IOPL; + op.u.iopl.domain = start_info.dom_id; + op.u.iopl.iopl = new_io_pl; + HYPERVISOR_dom0_op(&op); return 0; } diff --git a/xenolinux-2.4.21-sparse/arch/xeno/kernel/process.c b/xenolinux-2.4.21-sparse/arch/xeno/kernel/process.c index 06cb7a3563..86f8e680f4 100644 --- a/xenolinux-2.4.21-sparse/arch/xeno/kernel/process.c +++ b/xenolinux-2.4.21-sparse/arch/xeno/kernel/process.c @@ -44,6 +44,7 @@ #include #include #include +#include #include @@ -274,9 +275,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, __asm__ __volatile__ ( "pushfl; popl %0" : "=r" (eflags) : ); p->thread.io_pl = (eflags >> 12) & 3; - /* We're careful with hypercall privileges. Don't allow inheritance. */ - p->thread.hypercall_pl = 1; - return 0; } @@ -371,9 +369,14 @@ void __switch_to(struct task_struct *prev_p, struct task_struct *next_p) } queue_multicall2(__HYPERVISOR_stack_switch, __KERNEL_DS, next->esp0); - /* Next call will silently fail if we are a non-privileged guest OS. */ - queue_multicall2(__HYPERVISOR_set_priv_levels, - next->io_pl, next->hypercall_pl); + if ( start_info.flags & SIF_PRIVILEGED ) + { + dom0_op_t op; + op.cmd = DOM0_IOPL; + op.u.iopl.domain = start_info.dom_id; + op.u.iopl.iopl = next->io_pl; + queue_multicall1(__HYPERVISOR_dom0_op, (unsigned long)&op); + } /* EXECUTE ALL TASK SWITCH XEN SYSCALLS AT THIS POINT. */ execute_multicall_list(); diff --git a/xenolinux-2.4.21-sparse/arch/xeno/kernel/setup.c b/xenolinux-2.4.21-sparse/arch/xeno/kernel/setup.c index 0c3474e4ca..80f55c6cb6 100644 --- a/xenolinux-2.4.21-sparse/arch/xeno/kernel/setup.c +++ b/xenolinux-2.4.21-sparse/arch/xeno/kernel/setup.c @@ -43,6 +43,7 @@ #include #include #include +#include shared_info_t *HYPERVISOR_shared_info; @@ -301,12 +302,16 @@ void __init setup_arch(char **cmdline_p) paging_init(); - current->thread.hypercall_pl = 1; - if ( start_info.flags & SIF_PRIVILEGED ) { - current->thread.io_pl = 1; - /* We are privileged guest os - should have IO privileges. */ - if( HYPERVISOR_set_priv_levels(1, 1) ) + /* We are privileged guest os - should have IO privileges. */ + if ( start_info.flags & SIF_PRIVILEGED ) + { + dom0_op_t op; + op.cmd = DOM0_IOPL; + op.u.iopl.domain = start_info.dom_id; + op.u.iopl.iopl = 1; + if( HYPERVISOR_dom0_op(&op) != 0 ) panic("Unable to obtain IOPL, despite being SIF_PRIVILEGED"); + current->thread.io_pl = 1; } if(start_info.flags & SIF_CONSOLE) diff --git a/xenolinux-2.4.21-sparse/include/asm-xeno/hypervisor.h b/xenolinux-2.4.21-sparse/include/asm-xeno/hypervisor.h index da0e1a19e0..abf109b2ca 100644 --- a/xenolinux-2.4.21-sparse/include/asm-xeno/hypervisor.h +++ b/xenolinux-2.4.21-sparse/include/asm-xeno/hypervisor.h @@ -364,16 +364,4 @@ static inline long HYPERVISOR_kbd_op(unsigned char op, unsigned char val) return ret; } -static inline long HYPERVISOR_set_priv_levels(unsigned int new_io_pl, - unsigned int new_hypercall_pl) -{ - int ret; - __asm__ __volatile__ ( - TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_set_priv_levels), - "b" (new_io_pl), "c" (new_hypercall_pl) ); - - return ret; -} - #endif /* __HYPERVISOR_H__ */ diff --git a/xenolinux-2.4.21-sparse/include/asm-xeno/processor.h b/xenolinux-2.4.21-sparse/include/asm-xeno/processor.h index 3c4fa92b41..c47e348c53 100644 --- a/xenolinux-2.4.21-sparse/include/asm-xeno/processor.h +++ b/xenolinux-2.4.21-sparse/include/asm-xeno/processor.h @@ -358,7 +358,7 @@ struct thread_struct { unsigned long esp; unsigned long fs; unsigned long gs; - unsigned int io_pl, hypercall_pl; + unsigned int io_pl; /* Hardware debugging registers */ unsigned long debugreg[8]; /* %%db0-7 debug registers */ /* fault info */ -- 2.30.2